package com.ksvip.next.components.groovy.loader;

import java.util.ArrayList;
import java.util.List;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.NonNull;
import org.springframework.util.CollectionUtils;
import org.springframework.util.DigestUtils;

import com.google.common.base.Preconditions;
import com.ksvip.next.components.groovy.properties.GroovyMysqlLoaderProperties;
import com.ksvip.next.components.groovy.compiler.DynamicCodeCompiler;
import com.ksvip.next.components.groovy.entity.EnhanceGroovyScript;
import com.ksvip.next.components.groovy.entity.ScriptEntry;
import com.ksvip.next.components.groovy.entity.ScriptQuery;

/**
 * 从MySQL数据库里加载脚本
 */
@Slf4j
@AllArgsConstructor
public class MysqlScriptLoader implements ScriptLoader {
    private final Logger                  logger = LoggerFactory.getLogger(this.getClass());
    private DynamicCodeCompiler           dynamicCodeCompiler;
    private GroovyMysqlLoaderProperties   groovyMysqlLoaderProperties;
    private EnhanceGroovyScriptRepository enhanceGroovyScriptRepository;

    @Override
    public ScriptEntry load(@NonNull ScriptQuery query) throws Exception {
        // 按条件查询脚本
        EnhanceGroovyScript groovyScriptQuery = new EnhanceGroovyScript();
        groovyScriptQuery = groovyScriptQuery.queryConverter(query);
        groovyScriptQuery.setStatus("ON");
        List<EnhanceGroovyScript> groovyScripts = this.enhanceGroovyScriptRepository
                .selectByCondition(groovyScriptQuery);

        if (CollectionUtils.isEmpty(groovyScripts)) {
            this.logger.warn("can not found groovy script by condition : {}", groovyScriptQuery);
            return null;
        }
        EnhanceGroovyScript groovyScript = groovyScripts.get(0);
        String scriptContent = groovyScript.getScriptContent();
        // 获取脚本指纹
        String fingerprint = DigestUtils.md5DigestAsHex(scriptContent.getBytes());
        // 创建脚本对象
        ScriptEntry scriptEntry = new ScriptEntry(groovyScript.buildOnlyKey(), scriptContent, fingerprint,
                System.currentTimeMillis());
        // 动态加载脚本为Class
        Class<?> aClass = this.dynamicCodeCompiler.compile(scriptEntry);
        scriptEntry.setClazz(aClass);

        return scriptEntry;
    }

    @Override
    public List<ScriptEntry> load() {
        this.logger.info("load all groovy script start.");
        List<ScriptEntry> resultList = new ArrayList<>();
        EnhanceGroovyScript query = new EnhanceGroovyScript();
        query.setStatus("ON");
        query.setNamespace(this.groovyMysqlLoaderProperties.getNamespace());
        Preconditions.checkArgument(StringUtils.isNotBlank(query.getNamespace()));
        // 加载该命名空间下所有的脚本
        List<EnhanceGroovyScript> enhanceGroovyScripts = this.enhanceGroovyScriptRepository.selectByCondition(query);

        // 没有查到脚本，则不处理
        if (CollectionUtils.isEmpty(enhanceGroovyScripts)) {
            this.logger.warn("can not found EnhanceGroovyScripts by condition : [{}].", query);
            return resultList;
        }

        this.logger.info("==load groovy script count is : [{}]==", enhanceGroovyScripts.size());

        for (EnhanceGroovyScript groovyScript : enhanceGroovyScripts) {
            String scriptContent = groovyScript.getScriptContent();
            // 空脚本不处理
            if (StringUtils.isBlank(scriptContent)) {
                this.logger.error("script content is blank , groovyScript is : {}.", groovyScript);
                continue;
            }
            // 获取脚本指纹
            String fingerprint = DigestUtils.md5DigestAsHex(scriptContent.getBytes());
            // 创建脚本对象
            ScriptEntry scriptEntry = new ScriptEntry(groovyScript.buildOnlyKey(), scriptContent, fingerprint,
                    System.currentTimeMillis());
            resultList.add(scriptEntry);
        }

        this.logger.info("load all groovy script success.");

        return resultList;
    }
}
